package org.dromara.bclt.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.bclt.domain.Course;
import org.dromara.bclt.domain.DeviceInfo;
import org.dromara.bclt.domain.InferenceLog;
import org.dromara.bclt.domain.bo.DeviceInfoBo;
import org.dromara.bclt.domain.bo.InferenceLogBo;
import org.dromara.bclt.domain.vo.DeviceInfoVo;
import org.dromara.bclt.mapper.DeviceInfoMapper;
import org.dromara.bclt.mapper.InferenceLogMapper;
import org.dromara.bclt.service.DroolsPusheDataService;
import org.dromara.bclt.service.IInferenceLogService;
import org.dromara.bclt.websocket.constant.ChatConstants;
import org.dromara.bclt.websocket.domain.ChatMessage;
import org.dromara.bclt.websocket.service.ChatService;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.constant.TenantConstants;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.SysUserOnline;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RequiredArgsConstructor
@Service
public class DroolsPusheDataImpl implements DroolsPusheDataService {

    private final KieContainer kieContainer;
    private final IInferenceLogService inferenceLogService;
    private final InferenceLogMapper inferenceLogMapper;
    private final DeviceInfoMapper deviceInfoMapper;
    private final ChatService chatService;

    @DubboReference
    private final RemoteUserService remoteUserService;
    private DeviceInfoBo deviceInfoBo;

    @Scheduled(cron = "0 0 8,12,16,20 * * ?")
    @Override
    public void inference() {
        TenantHelper.setDynamic(TenantConstants.DEFAULT_TENANT_ID);

        //TODO: 获取在线app用户列表
        List<SysUserOnline> sysUserOnlineInfo = getAndroidOnlineUserlist().getRows();
        System.out.println("sysUserOnlineInfo：" + sysUserOnlineInfo);
        System.out.println("有几条数据：" + sysUserOnlineInfo.size());
        List<InferenceLogBo> userList = new ArrayList<>();
        // 遍历在线用户列表
        if (!sysUserOnlineInfo.isEmpty()) {
            for (SysUserOnline userOnline : sysUserOnlineInfo) {
                InferenceLogBo inferenceLogBo = new InferenceLogBo();
                inferenceLogBo.setUserName(userOnline.getUserName());

                if (StringUtils.isNotEmpty(userOnline.getUserName())) {
                    // 通过远程服务获取用户信息
                    Long userId = remoteUserService.getUserIdByUserName(userOnline.getUserName());
                    if (userId != null) {
                        // TODO: 根据用户ID进行后续处理
                        inferenceLogBo.setUserId(userId);
                    }
                    DeviceInfoVo deviceInfoVo = deviceInfoMapper.selectVoOne(new LambdaQueryWrapper<DeviceInfo>()
                        .select(DeviceInfo::getDeviceNumber, DeviceInfo::getId)
                        .eq(DeviceInfo::getUserName, userOnline.getUserName()));
                    if (deviceInfoVo != null) {
                        inferenceLogBo.setDeviceNumber(deviceInfoVo.getDeviceNumber());
                        inferenceLogBo.setDeviceId(deviceInfoVo.getId());
                    }
                }
                userList.add(inferenceLogBo);
            }
        }
        for (int i = 0; i < userList.size(); i++) {
            System.out.println("开始处理第 " + (i + 1) + " 个用户");
            deviceInfoBo = new DeviceInfoBo();
            deviceInfoBo.setDeviceNumber(userList.get(i).getDeviceNumber());
            System.out.println("准备调用InferenceData，deviceInfoBo: " + deviceInfoBo);
            try {
                InferenceLogBo inferenceLogBo = inferenceLogService.InferenceData(deviceInfoBo);
                System.out.println("InferenceData调用完成，返回结果: " + inferenceLogBo);
                System.out.println("InferenceData状态: " + inferenceLogBo.getCurrentCourseReminderStatus());

                //从Kie容器对象中获取会话对象
                KieSession session = kieContainer.newKieSession();
                // Redis 获取值
                Integer valueForExercise = RedisUtils.getCacheObject(deviceInfoBo.getDeviceNumber() + "currentExerciseReminderStatus");
                Integer valueForCourse = RedisUtils.getCacheObject(deviceInfoBo.getDeviceNumber() + "currentCourseReminderStatus");
                if (valueForExercise == null) {
                    valueForExercise = 0;
                }
                if (valueForCourse == null) {
                    valueForCourse = 0;
                }

                inferenceLogBo.setCurrentExerciseReminderStatus(valueForExercise);
                inferenceLogBo.setCurrentExerciseReminderStatus(valueForCourse);
//                if (inferenceLogBo.getNoticeNumber() != 4) {
//                    //将Order对象插入到工作内存中
//                    session.insert(inferenceLogBo);
//
//                    //激活规则，由Drools框架自动进行规则匹配，如果规则匹配成功，则执行当前规则
//                    session.fireAllRules();
//                    //关闭会话
//                    session.dispose();
//                }else {
//                    System.out.println("第4次只计算，不推送");
//                }
//                将Order对象插入到工作内存中
                session.insert(inferenceLogBo);

                    //激活规则，由Drools框架自动进行规则匹配，如果规则匹配成功，则执行当前规则
                session.fireAllRules();
                    //关闭会话
                session.dispose();
                RedisUtils.setCacheObject(deviceInfoBo.getDeviceNumber() + "currentExerciseReminderStatus", inferenceLogBo.getCurrentExerciseReminderStatus());
                RedisUtils.setCacheObject(deviceInfoBo.getDeviceNumber() + "currentCourseReminderStatus", inferenceLogBo.getCurrentCourseReminderStatus()); //0 或 1

                System.out.println("valueForExercise: " + RedisUtils.getCacheObject(deviceInfoBo.getDeviceNumber() + "currentExerciseReminderStatus"));
                System.out.println("valueForCourse: " + RedisUtils.getCacheObject(deviceInfoBo.getDeviceNumber() + "currentCourseReminderStatus"));

                //                System.out.println("推理日志数据: " + inferenceLogBo);
                InferenceLog inferenceLog = MapstructUtils.convert(inferenceLogBo, InferenceLog.class);
//                System.out.println("转换后的实体: " + inferenceLog);
//                if(inferenceLog.getCourseReminderCycle() == 0) {
//                    inferenceLog.
//                }
                int result = inferenceLogMapper.insert(inferenceLog);
                System.out.println("插入结果: " + result);
                if (result > 0) {
                    System.out.println("插入成功");
                } else {
                    System.out.println("插入失败");
                }
                // 通过WebSocket发送消息
                if (StringUtils.isNotEmpty(String.valueOf(inferenceLog.getDeviceId()))) {
                    ChatMessage message = new ChatMessage();
                    message.setType(ChatConstants.MESSAGE_TYPE_TEXT);
                    message.setSenderId(0L); // 系统发送
                    message.setSenderName("系统");
                    message.setReceiverId(userList.get(i).getUserId());
                    System.out.println("userList.get(i).getUserId(): " + userList.get(i).getUserId());
                    message.setContent(inferenceLog.getContent());
                    message.setReadStatus(ChatConstants.MESSAGE_STATUS_UNREAD);
                    chatService.sendMessage(message);
                }
            } catch (Exception e) {
                System.out.println("处理过程中发生异常: " + e.getMessage());
                e.printStackTrace();
            }
        }

        //TODO: 根据用户账号userName 查询设备id / 设备deviceNumber
        //TODO: 绑定关系：用户列表的id，用户账号和设备id
        //TODO: for循环为每个用户进行推理
        //TODO: 推理完成后进行存储 并推送至app


    }
    public TableDataInfo<SysUserOnline> getAndroidOnlineUserlist() {
        // 获取所有未过期的 token
        List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
        List<SysUserOnline> userOnlineDTOList = new ArrayList<>();
        for (String key : keys) {
            String token = StringUtils.substringAfterLast(key, ":");
            // 如果已经过期则跳过
            if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) {
                continue;
            }
            SysUserOnline userOnline = RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token);
            if (userOnline != null && "android".equals(userOnline.getDeviceType())) {
                userOnlineDTOList.add(userOnline);
            }

        }
        Collections.reverse(userOnlineDTOList);
        userOnlineDTOList.removeAll(Collections.singleton(null));
        List<SysUserOnline> userOnlineList = BeanUtil.copyToList(userOnlineDTOList, SysUserOnline.class);
        System.out.println("userOnlineList: " + userOnlineList);

        return TableDataInfo.build(userOnlineList);
    }



}
